<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
	/**
	 * CodeIgniter
	 *
	 * An open source application development framework for PHP 4.3.2 or newer
	 *
	 * @package		CodeIgniter
	 * @author		ExpressionEngine Dev Team
	 * @copyright	Copyright (c) 2008 - 2009, EllisLab, Inc.
	 * @license		http://codeigniter.com/user_guide/license.html
	 * @link		http://codeigniter.com
	 * @since		Version 1.0
	 * @filesource
	 */
	// ------------------------------------------------------------------------
	
	/**
	 * @package		CodeIgniter
	 * @subpackage	Libraries
	 * @author		AnhDT
	 */
	 
	class st_menu {
		/**Tiền tố và hậu tố của lớp menu renderer*/
		const PREFIX_RENDERER = 'st_menu_';
		/**Tiền tố và hậu tố của lớp menu renderer*/
		const SUFFIX_RENDERER = '_renderer';
		/**Kiểu render mặc định của menu*/
		protected static $_defaultRenderer = 'superfish';
		/**Bộ render của menu*/
		protected $_render = null;
		/**Định danh của menu*/
		protected static $_instance   = null;
		/**id của menu*/
		protected $_id         = '';
		/**class của menu*/
		protected $_classes     = array();
		/**url của menu*/
		protected $_url        = '';
		/**Gợi ý của menu*/
		protected $_tooltip    = '';
		/**Ảnh đại diện của menu*/
		protected $_icon       = '';
		/**Cha của menu*/
		protected $_parent     = null;
		/**Các con của menu*/
		protected $_children   = array();
		/**số lượng con của menu*/
		protected $_countChildren = 0;
		/**Tiêu đề của menu*/
		protected $_title      = '';
		/**Tên menu*/
		protected $_name       = '';
		/**Các thiết lập tùy chọn*/
		protected $_option     = array(
							 	'isMenuContainer' => true,
								'showHtml'        => true,
								'maxChildren'     => 100
							 );
		/**Dữ liệu được lưu cache*/
		protected $_cachedData = null;
		/**Cấp độ của menu, cấp độ con sẽ bằng cấp độ cha + 1*/
		protected $_level      = 0;
		/**Thuật toán bao đóng có dạng: parent_id/child_id*/
		protected $_closure    = '';
		/**Vị trí của menu*/
		protected $_order      = 1;
		/**Menu là menu hiện thời*/
		protected $_isCurrent  = false;
		/**Tên class được dùng để kích hoạt menu*/
		protected $_activeClass = '';
		
		/**Hàm khởi tạo*/
		function __construct($_title = '', $_url = '', $_options = array()) {
			$this->factory($_title, $_url, $_options);
		}
		
		/**Hàm khởi tạo các thông tin cho menu*/
		public function factory($_title = '', $_url = '', $_options = array()) {
			$this->setTitle($_title);
			$this->setUrl($_url);
			$this->setOptions($_options);
			return $this;
		}
		
		/**Singleton Pattern*/
		public function getInstance() {
			if (null === self::$_instance) {
				self::$_instance = new self;
			}	
			return self::$_instance;
		}
		
		/**Thiết lập option cho menu*/
		public function setOptions($_options = array()) {
			if (!count($_options) === 0) {
				return false;	
			}
			return $this;
		}
		
		/** Lấy về các thiết lập tùy chọn*/
		public function getOption($_option) {
			if (isset($this->_option[$_option])) {
				return $this->_option[$_option];
			}
			return false;
		}
		
		/**Thiết lập option cho menu*/
		public function setOption($_option, $_value) {
			if (!is_string($_option) || empty($_option) || empty($_value)) {
				return false;	
			}
			$this->_option[$_option] = $_value;
			return $this;
		}
		
		/** Lấy về các thiết lập tùy chọn*/
		public function getOptions() {
			return $this->_option;
		}
		
		/**Đặt tên cho menu*/
		public function setName($_name = '') {
			if (!is_string($_name) || empty($_name)) {
				return false;	
			}
			$this->_name = $_name;
			return $this;
		}
		
		/**Lấy về tên của menu*/
		public function getName() {
			return $this->_name;
		}
		
		/**Đặt tiêu đề cho menu*/
		public function setTitle($_title = '') {
			if (empty($_title)) {
				return false;	
			}
			$this->_title = $_title;
			return $this;
		}
		
		/**Lấy về tiêu đề của menu*/
		public function getTitle() {
			return $this->_title;
		}
		
		/**Đặt tooltip cho menu*/
		public function setTooltip($_tooltip = '') {
			if (empty($_tooltip)) {
				return false;	
			}
			$this->_tooltip = $_tooltip;
			return $this;
		}
		
		/**Lấy về tooltip của menu*/
		public function getTooltip() {
			return $this->_tooltip;
		}
		
		/**Đặt url cho menu*/
		public function setUrl($_url = '') {
			if (empty($_url)) {
				return false;	
			}
			$this->_url = $_url;
			return $this;
		}
		
		/**Lấy về url của menu*/
		public function getUrl() {
			return $this->_url;
		}
		
		/**Đặt vị trí cho menu*/
		public function setOrder($_order = 1) {
			$this->_order = $_order;
			return $this;
		}
		
		/**Lấy về vị trí của menu*/
		public function getOrder() {
			return $this->_order;
		}
		
		/**Thiết lập id cho menu*/
		public function setId($_id = '') {
			if (empty($_id)) {
				$_id = $this->_autoGenId();	
			}
			$this->_id = $_id;	
			return $this;
		}
		
		/**Lấy về id*/
		public function getId() {
			return $this->_id;	
		}
		
		/**Lưu trữ vào dữ liệu ở bộ đệm*/
		public function setCachedData($_data = '') {
			if (empty($_data)) {
				return false;	
			}
			$this->_cachedData = serialize($_data);
			return $this;
		}
		
		/**Lấy về dữ liệu ở bộ đệm*/
		public function getCachedData() {
			return unserialize($this->_cachedData);	
		}
		
		/**Tự phát sinh ra id*/
		protected function _autoGenId() {
			return get_class($this) . '_' . md5(time());	
		}

		/**Đặt cha của menu*/
		public function setParent(st_menu $_parent) {
			$this->_parent  = & $_parent;
			if (!$_parent->hasChild($this->getId())) {
				$_parent->addChild($this);	
			}
			$this->_level   = $_parent->getLevel() + 1;
			$this->_closure = $_parent->getId() . '/' . $this->getId();
			return $this;				
		}
		
		/**Lấy về cha của menu*/
		protected function getParent() {
			return $this->_parent;	
		}
		
		/**Lấy về level của menu*/
		public function getLevel() {
			return intval($this->_level);	
		}
		
		/**Thiết lập icon cho menu*/
		public function setIcon($_path = '') {
			if (empty($_path) || !file_exists($_path)) {
				return false;	
			}
			$this->_icon = $_path;
			return $this;
		}
		
		/**Lấy về icon của menu*/
		public function getIcon() {
			return $this->_icon;	
		}
		
		/**Thêm 1 class*/
		public function addClass($_class) {
			if (empty($_class)) {
				return false;	
			}
			$this->_classes[$_class] = $_class;
			return $this;
		}
		
		/**Kiểm tra menu có nằm trong class đó không*/
		public function hasClass($_class) {
			if (!isset($this->_classes[$_class])) {
				return false;	
			}
			return true;
		}
		
		/**Gỡ 1 class*/
		public function removeClass($_class) {
			if ($this->hasClass($_class)) {
				return false;	
			}
			unset($this->_classes[$_class]);
			return $this;
		}
		
		/**Thiết lập các class*/
		public function setClasses($_classes = array()) {
			if (empty($_classes) || !is_array($_classes)) {
				return false;	
			}
			$this->_classes = $_classes;
			return $this;
		}
		
		/**Lấy về các class*/
		public function getClasses() {
			return $this->_classes;
		}
		
		/**Reset các class*/
		public function resetClasses() {
			$this->_classes	= array();
			return $this;
		}
		
		/**Thêm 1 menu con*/
		public function addChild(st_menu $_child) {
			if ($this->getOption('isMenuContainer')) {
				if ($this->countChildren() + 1 <= intval($this->getOption('maxChildren'))) {
					$this->_children[$_child->getId()] = $_child;
					$this->_countChildren = count($this->_children);
					// Thêm cha
					$_child->setParent($this);
					return $this;
				}
			}
			return false;
		}
		
		//Kiểm tra menu có nằm trong class đó không
		public function hasChild($_child) {
			if (is_string($_child)) {
				if (!isset($this->_children[$_child])) {
					return false;	
				}
			} elseif ($_child instanceof st_menu) {
				if (!isset($this->_children[$_child->getId()])) {
					return false;	
				}
			}
			return true;
		}
		
		//Gỡ 1 menu con
		public function removeChild($_child) {
			if ($this->hasChild($_child)) {
				return false;	
			}
			if ($_child instanceof st_menu) {
				unset($this->_children[$_child->getId()]);	
			} elseif (is_string($_child)) {
				unset($this->_children[$_child]);	
			}
			return $this;
		}
		
		/**Thiết lập các children*/
		public function setChilren($_children = array()) {
			if (empty($_children) || !is_array($_children)) {
				return false;	
			}
			foreach ($_children as $_id => $_child) {
				if (empty($_id) || !$_child instanceof st_menu) {
					continue;
				}
				$this->_children[] = $_child;				
			}
			return $this;
		}
		
		/**Lấy về children*/
		public function getChildren() {
			return $this->_children;
		}
		
		/**Lấy về một menu con*/
		public function getChild($_child) {
			if (!$this->hasChild($_child)) {
				return false;
			}
			if ($_child instanceof st_menu) {
				return $this->_children[$_child->getId()];	
			} elseif (is_string($_child)) {
				return $this->_children[$_child];		
			}
			return false;
		}
		
		/**Reset children*/
		public function resetChildren() {
			$this->_children	= array();
			return $this;
		}
		
		/**Đếm số lượng con của menu*/
		public function countChildren() {
			if ($this->_countChildren === 0) {
				$this->_countChildren = count($this->_children);	
			}
			return $this->_countChildren;
		}
		/**Xuất ra định dạng html*/
		public function outputHtml($_renderType = 'superfish') {
			if ($this->getOption('showHtml')) {
				$_output = $this->getOutputHtml($_renderType);					
				echo $_output;
			}
			return $this;
		}
		
		/**Lấy về dữ liệu html*/
		public function getOutputHtml($_renderType = 'superfish') {
			$_render = $this->_loadRenderType($_renderType);
			return $_render->getOutput();
		}
		
		/**Tải loại menu xuất ra*/
		protected function _loadRenderType($_renderType = '') {
			if (empty($_renderType)) {
				$_renderType = $this->getDefaultRenderType();	
			}
			$_renderType = self::PREFIX_RENDERER . $_renderType . self::SUFFIX_RENDERER;
			if (!class_exists($_renderType)) {
				require_once APP_LIBRARY_PATH . 'tree/menu/renderer/' . $_renderType . '.php';	
			}
			$_render = new $_renderType();
			$this->setRenderer($_render);
			return $_render;
		}
		
		/**Thiết lập bộ render cho menu*/
		public function setRenderer(st_menu_interface_renderer $_render) {	
			$this->_render = & $_render;
			$_render->setMenu($this);
			return $this;
		}
		
		/**Lấy về bộ render cho menu*/
		public function getRenderer() {
			return $this->_render;	
		}
		
		/**Lấy về tên kiểu bộ đệm render cho menu*/
		protected function getDefaultRenderType() {
			return self::$_defaultRenderer;	
		}
		
		/**Lấy về closure*/
		public function getClosure() {
			$_parent = & $this->getParent();
			if (empty($this->_closure)) {
				if (!empty($_parent)) {
					$this->_closure = $_parent->getId() . '/' . $this->getId();	
				} else {
					$this->_closure = '/' . $this->getId();			
				}
			}
			return $this->_closure;	
		}
		
		/**Lấy về closure*/
		public function setClosure($_closure = '') {
			$this->_closure = $_closure;
			return $this;	
		}
		
		/**Thiết lập menu là menu hiện thời đang được dùng*/
		public function setCurrent($_isCurrent = true) {
			$this->_isCurrent = (bool)$_isCurrent;	
			return $this;
		}
		
		/**Kiểm tra menu có phải là menu hiện thời không*/
		public function isCurrent() {
			return $this->_isCurrent;	
		}
		
		/**Thiết lập tên lớp được kích hoạt*/
		public function setActiveClass($_className) {
			$this->_activeClass = $_className;
			return $this;
		}
		
		/**Lấy về tên lớp được kích hoạt*/
		public function getActiveClass() {
			return $this->_activeClass;	
		}
		
		/**Lấy về menu con đầu tiên*/
		public function getFirstChild() {
			if ($this->countChildren() == 0) {
				return false;	
			}
			$_children = $this->_children;
			return array_pop($_children);
		}
	}
?>